package cn.dduan.fool.design.pattern.structure.adaptor;

/**
 * 适配器模式
 * <p>
 * 优点：
 * 1、适配器模式主要用于将一个类或者接口转化成客户端希望的格式，使得原本不兼容的类可以在一起工作，将目标类和适配者类解耦
 * 2、同时也符合“开闭原则”，可以在不修改原代码的基础上增加新的适配器类
 * 3、将具体的实现封装在适配者类中，对于客户端类来说是透明的，而且提高了适配者的复用性
 * <p>
 * 缺点：
 * 1、在于更换适配器的实现过程比较复杂
 * <p>
 * 适用场景：
 * 1、系统需要使用现有的类，而这些类的接口不符合系统的接口
 * 2、使用第三方组件，组件接口定义和自己定义的不同，不希望修改自己的接口，但是要使用第三方组件接口的功能
 * <p>
 * 实现方式：
 * 1、类的适配器模式：当希望将一个类转换成满足另一个新接口的类时，可以使用类的适配器模式，创建一个新类，继承原有的类，实现新的接口即可
 * 2、对象的适配器模式：当希望将一个对象转换成满足另一个新接口的对象时，可以创建一个Wrapper类，持有原类的一个实例，在Wrapper类的方法中，调用实例的方法就行
 * 3、接口的适配器模式：当不希望实现一个接口中所有的方法时，可以创建一个抽象类Wrapper，实现所有方法，我们写别的类的时候，继承抽象类即可
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
public class AdaptorPattern {
    public static void main(String[] args) {
        // 使用普通功能类
        Target concreteTarget = new ConcreteTarget();
        concreteTarget.request();

        // 使用特殊功能类，即适配类
        Target adapter = new ClassAdapter();
        adapter.request();

        // 对象的适配器模式
        Target objAdapter = new ObjectAdapter(new Adaptee());
        objAdapter.request();

        // 接口的适配器模式
        Sourceable sourceable1 = new SourceSub1();
        Sourceable sourceable2 = new SourceSub2();
        sourceable1.fun1();
        sourceable1.fun2();
        sourceable2.fun1();
        sourceable2.fun2();
    }
}

/**
 * 需要适配的类（Adaptee）
 * 已存在的、具有特殊功能、但不符合我们既有的标准接口的类
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class Adaptee {
    public void specificRequest() {
        System.out.println("被适配类具有 特殊功能...");
    }
}

/**
 * 目标接口（Target）
 * 目标接口，或称为标准接口
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
interface Target {
    public void request();
}

/**
 * 具体目标类，只提供普通功能
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class ConcreteTarget implements Target {
    @Override
    public void request() {
        System.out.println("普通类 具有 普通功能...");
    }
}

/**
 * 类的适配器模式
 * 适配器类，继承了被适配类，同时实现标准接口
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class ClassAdapter extends Adaptee implements Target {
    @Override
    public void request() {
        super.specificRequest();
    }
}

/**
 * 对象的适配器模式
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class ObjectAdapter extends Adaptee implements Target {
    /**
     * 直接关联适配器类
     */
    private Adaptee adaptee;

    /**
     * 可以通过构造函数传入具体需要适配的被适配类对象
     *
     * @param adaptee
     * @return
     * @author dduan
     * @version 1.0
     * @date 2023/4/7
     */
    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        // 使用委托的方式完成特殊功能
        this.adaptee.specificRequest();
    }
}

/**
 * 原接口
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
interface Sourceable {
    public void fun1();

    public void fun2();
}

abstract class Wrapper implements Sourceable {
    @Override
    public void fun1() {
    }

    @Override
    public void fun2() {
    }
}

class SourceSub1 extends Wrapper {
    @Override
    public void fun1() {
        System.out.println("这是实现Sourceable接口的：" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }
}

class SourceSub2 extends Wrapper {
    @Override
    public void fun2() {
        System.out.println("这是实现Sourceable接口的：" + Thread.currentThread().getStackTrace()[1].getMethodName());
    }
}